"""
Webhook integration for receiving notifications from third-party systems
"""
import json
import hashlib
import hmac
from datetime import datetime
from typing import Dict, Any, Optional
from fastapi import Request, HTTPException
import os

# Directory to store webhook configurations
WEBHOOKS_DIR = "webhooks"
os.makedirs(WEBHOOKS_DIR, exist_ok=True)


class WebhookReceiver:
    """
    A class to handle incoming webhooks from third-party systems
    """
    
    def __init__(self):
        self.webhooks_config = self.load_webhooks_config()
    
    def load_webhooks_config(self) -> Dict:
        """Load webhook configurations from file"""
        config_file = os.path.join(WEBHOOKS_DIR, "webhooks_config.json")
        if os.path.exists(config_file):
            with open(config_file, 'r', encoding='utf-8') as f:
                return json.load(f)
        return {}
    
    def save_webhooks_config(self):
        """Save webhook configurations to file"""
        config_file = os.path.join(WEBHOOKS_DIR, "webhooks_config.json")
        with open(config_file, 'w', encoding='utf-8') as f:
            json.dump(self.webhooks_config, f, ensure_ascii=False, indent=2)
    
    def verify_signature(self, payload: bytes, signature: str, secret: str) -> bool:
        """
        Verify the signature of the incoming webhook
        """
        if not signature or not secret:
            return True  # Skip verification if no signature or secret
        
        expected_signature = hmac.new(
            secret.encode('utf-8'),
            payload,
            hashlib.sha256
        ).hexdigest()
        
        # Compare signatures securely to prevent timing attacks
        return hmac.compare_digest(f"sha256={expected_signature}", signature)
    
    def register_webhook(self, webhook_id: str, config: Dict[str, Any]) -> bool:
        """
        Register a new webhook configuration
        """
        try:
            self.webhooks_config[webhook_id] = {
                "id": webhook_id,
                "config": config,
                "created_at": datetime.now().isoformat(),
                "enabled": True
            }
            self.save_webhooks_config()
            return True
        except Exception:
            return False
    
    def handle_webhook(self, webhook_id: str, payload: bytes, signature: Optional[str] = None) -> Dict[str, Any]:
        """
        Handle an incoming webhook request
        """
        if webhook_id not in self.webhooks_config:
            raise HTTPException(status_code=404, detail="Webhook not found")
        
        webhook_config = self.webhooks_config[webhook_id]
        
        if not webhook_config.get("enabled", True):
            raise HTTPException(status_code=403, detail="Webhook is disabled")
        
        # Verify signature if secret is configured
        secret = webhook_config["config"].get("secret")
        if secret and signature:
            if not self.verify_signature(payload, signature, secret):
                raise HTTPException(status_code=401, detail="Invalid signature")
        
        # Process the payload based on the webhook configuration
        try:
            payload_json = json.loads(payload.decode('utf-8'))
        except json.JSONDecodeError:
            raise HTTPException(status_code=400, detail="Invalid JSON payload")
        
        # Determine what to do based on the webhook configuration
        action = webhook_config["config"].get("action", "log")
        
        if action == "create_template":
            return self.handle_create_template_webhook(payload_json, webhook_config)
        elif action == "send_card":
            return self.handle_send_card_webhook(payload_json, webhook_config)
        elif action == "trigger_automation":
            return self.handle_automation_webhook(payload_json, webhook_config)
        else:
            # Default action is to log the webhook
            return self.handle_default_webhook(payload_json, webhook_id)
    
    def handle_create_template_webhook(self, payload: Dict, config: Dict) -> Dict[str, Any]:
        """
        Handle webhook that creates a new template
        """
        from main import TEMPLATES_DIR, get_template_metadata, save_template_metadata
        import os
        import json
        
        try:
            # Extract template details from payload
            template_name = payload.get("template_name") or config["config"].get("default_template_name")
            template_content = payload.get("content") or payload
            
            if not template_name:
                return {"error": "Template name is required"}
            
            # Save template
            filepath = os.path.join(TEMPLATES_DIR, f"{template_name}.json")
            with open(filepath, 'w', encoding='utf-8') as f:
                json.dump(template_content, f, ensure_ascii=False, indent=2)
            
            # Save metadata
            category = config["config"].get("default_category", "Webhook")
            tags = config["config"].get("default_tags", ["webhook"])
            
            metadata = get_template_metadata(template_name)
            metadata["category"] = category
            metadata["tags"] = tags
            save_template_metadata(template_name, metadata)
            
            return {
                "message": f"Template {template_name} created from webhook",
                "template_name": template_name,
                "action": "create_template"
            }
        except Exception as e:
            return {"error": f"Failed to create template: {str(e)}"}
    
    def handle_send_card_webhook(self, payload: Dict, config: Dict) -> Dict[str, Any]:
        """
        Handle webhook that sends a card directly
        """
        from dingtalk_api import send_card_to_dingtalk
        
        try:
            # Get webhook URL and secret from config or payload
            webhook_url = payload.get("webhook_url") or config["config"].get("webhook_url")
            secret = payload.get("secret") or config["config"].get("secret")
            card_content = payload.get("content")
            
            if not webhook_url or not card_content:
                return {"error": "Webhook URL and content are required for sending card"}
            
            # Send card via DingTalk API
            result = send_card_to_dingtalk(card_content, webhook_url, secret)
            
            return {
                "message": "Card sent via webhook",
                "result": result,
                "action": "send_card"
            }
        except Exception as e:
            return {"error": f"Failed to send card: {str(e)}"}
    
    def handle_automation_webhook(self, payload: Dict, config: Dict) -> Dict[str, Any]:
        """
        Handle webhook that triggers an automation
        """
        # This could trigger various automation workflows
        # For now, we'll just log the event
        from logging_config import log_info
        
        log_info(
            f"Automation webhook triggered with payload: {payload}",
            endpoint="/api/webhook/automation",
            user="system"
        )
        
        return {
            "message": "Automation webhook received",
            "payload_keys": list(payload.keys()),
            "action": "automation"
        }
    
    def handle_default_webhook(self, payload: Dict, webhook_id: str) -> Dict[str, Any]:
        """
        Default handler that logs the webhook
        """
        from logging_config import log_info
        
        log_info(
            f"Webhook {webhook_id} received with payload: {payload}",
            endpoint=f"/api/webhook/{webhook_id}",
            user="system"
        )
        
        return {
            "message": f"Webhook {webhook_id} received",
            "payload_keys": list(payload.keys()),
            "action": "log"
        }


# Global instance
webhook_receiver = WebhookReceiver()